﻿using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace NetstsadmService
{
    public partial class MainForm : Form, ILogger
    {
        enum ServiceStatus
        {
            Running,
            Waiting
        }

        FormWindowState previousWindowState;
        const int PORT_NUMBER_DEFAULT = 1478;
        Config cfg;
        Host serviceHost;
        ServiceStatus serviceStatus = ServiceStatus.Waiting;

        int portNumber = PORT_NUMBER_DEFAULT;

        bool allowAnonymous
        {
            get { return cbAnonymous.Checked; }
        }

        public MainForm()
        {
            InitializeComponent();
        }

        #region Form Events handlers

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            SetLabels();
            RestoreParameters();
            // Start Logger notifier
            Logger logger = Logger.GetLogger();
            logger.LoggerComponent = this;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            // Stop the service
            if (serviceHost != null && serviceStatus == ServiceStatus.Running)
                serviceHost.Close();
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (this.WindowState != FormWindowState.Minimized) previousWindowState = this.WindowState;
            notifyIcon.Visible = (this.WindowState == FormWindowState.Minimized);
            this.Visible = !notifyIcon.Visible;
        }


        #endregion

        #region Initialisation methods

        void SetLabels()
        {
            gbServiceConfig.Text = Resource.SRV_PARAMS;
            lbPortNumber.Text = Resource.PORT_NB;
            butStartService.Text = Resource.START_SRV;
            cbAnonymous.Text = Resource.ANONYMOUS;
            ttAnonymous.SetToolTip(cbAnonymous, Resource.ANONYMOUS_VS_WINDOWS);
            gbOutput.Text = Resource.CMD_EXECUTED;
            tssStatusLabel.Text = Resource.SRV_NOT_RUNNING;
            toolStripCopy.Text = Resource.COPY_URL;
            butClear.Text = Resource.CLEAR;
            toolStripRestore.Text = Resource.RESTORE;
            toolStripCloseStop.Text = Resource.CLOSE_STOP;
        }

        void RestoreParameters()
        {
            cfg = Config.GetConfig();
            tbPortNumber.Text = (cfg.GetValue(Config.ConfigKeys.Port_Number) == "" ?
                PORT_NUMBER_DEFAULT.ToString() : cfg.GetValue(Config.ConfigKeys.Port_Number));

            bool allowAnonymous = false;
            Boolean.TryParse(cfg.GetValue(Config.ConfigKeys.Allow_Anonymous), out allowAnonymous);
            cbAnonymous.Checked = allowAnonymous;
        }

        #endregion

        #region UI Event handlers

        void tbPortNumber_Leave(object sender, EventArgs e)
        {
            if (!TryParsePortNumber(((TextBox)sender).Text))
            {
                ((TextBox)sender).Text = PORT_NUMBER_DEFAULT.ToString();
            }
        }

        void cbAnonymous_Leave(object sender, EventArgs e)
        {
            cfg.SetValue(Config.ConfigKeys.Allow_Anonymous,((CheckBox)sender).Checked.ToString());
        }

        void butStartService_Click(object sender, EventArgs e)
        {
            switch (serviceStatus)
            {
                case ServiceStatus.Waiting:
                    StartService();
                    break;
                case ServiceStatus.Running:
                    StopService();
                    break;
            }
        }

        void butClear_Click(object sender, EventArgs e)
        {
            tbOutput.Text = "";
        }

        void toolStripCopy_Click(object sender, EventArgs e)
        {
            if (serviceHost != null)
            {
                try
                {
                    Clipboard.Clear();
                    Clipboard.SetText(serviceHost.ListeningURL);
                }
                catch { }
            }
        }

        void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            restoreUI();   
        }

        void toolStripRestore_Click(object sender, EventArgs e)
        {
            restoreUI();
        }

        void toolStripCloseStop_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion

        bool TryParsePortNumber(string input)
        {
            int pn = -1;
            if (!Int32.TryParse(input, out pn))
            {
                return false;
            }
            if (pn < 1 || pn > 70000)
                return false;

            portNumber = pn;
            
            // Save it
            cfg.SetValue(Config.ConfigKeys.Port_Number, pn.ToString());
            
            return true;
        }

        void StartService()
        {
            serviceHost = new Host(portNumber, allowAnonymous);
            Thread thread = new Thread(new ThreadStart(serviceHost.Start));
            
            try
            {
                thread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0}\n{1}", Resource.ERROR_LAUNCH_SRV, ex.Message), Resource.ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            butStartService.Text = Resource.STOP_SRV;
            tssStatusLabel.Text = string.Format(Resource.SRV_RUNNING, serviceHost.ListeningURL);
            tbPortNumber.ReadOnly = true;
            cbAnonymous.Enabled = false;
            serviceStatus = ServiceStatus.Running;
        }

        void StopService()
        {
            try
            {
                serviceHost.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0}\n{1}", Resource.ERROR_STOP_SRV, ex.Message), Resource.ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            butStartService.Text = Resource.START_SRV;
            tssStatusLabel.Text = Resource.SRV_NOT_RUNNING;
            tbPortNumber.ReadOnly = false;
            cbAnonymous.Enabled = true;
            serviceStatus = ServiceStatus.Waiting;
        }

        void restoreUI()
        {
            this.Visible = true;
            notifyIcon.Visible = false;
            this.WindowState = previousWindowState;
        }

        #region ILogger Members

        public void Write(string Text)
        {
            tbOutput.Text += string.Format("{0}", Text);
            tbOutput.Text += Environment.NewLine;
        }

        #endregion
    }
}